import time
import warnings

MAX_STEPS = 15
import copy
from typing import Dict


class Data():
    '''
    这是一个数据对象，可以管理数据的历史。
    支持的对象类型应当是有限的，比如dataframe,ndarray等。
    '''

    def __init__(self, ini_value: object):
        self.value_stack = []
        self.stack_pointer = 0  # 指向起始位置的指针。以下代码注释中简称‘指针’
        self.info = {}
        self.set_data(ini_value)

    def __len__(self):
        return len(self.value_stack)

    def get_latest(self, copy_val=True) -> object:
        if copy_val:
            return copy.copy(self.value_stack[-1])
        return self.value_stack[-1]

    def set_data(self, value: object):
        '''
        添加数据。
        :param value:
        :return:
        '''
        self.value_stack.append(value)
        while len(self.value_stack) > MAX_STEPS:
            self.value_stack.pop(0)
        self.stack_pointer = len(self) - 1
        self.update_info()

    def get_data(self, copy_val=True) -> object:
        '''
        获取数据的值，采用当前的指针。
        :param copy_val:
            如果为True(默认)，就返回复制后的对象。反之返回引用。当需要修改对象的时候，请保持True。
            特别的，不要使用类似如下的方式。这样会多次复制对象，从而导致不必要的开销：
                for i in range(10):
                    Data.get('a')[i]
                可以使用如下方案：
                for i in range(10):
                    Data.get('a',copy=False)[i]
                但还是推荐使用：
                a = Data.get('a')
                for i in range(10):
                    a[i]
        :return:object
        '''
        index = self.stack_pointer
        if copy_val:
            return copy.copy(self.value_stack[index])
        return self.value_stack[index]

    def get_index(self) -> int:
        return self.stack_pointer

    def set_index(self, index: int):
        if 0 <= index < len(self.value_stack):
            self.stack_pointer = index

    def update_info(self):  # 目前逻辑是写死了的。
        name = 'test_file'
        path = '../class.csv'
        create_time = '2017.9.1'#self.info['create_time']
        update_time = '时间戳：' + str(time.time())
        row = '10'
        col = '10'
        remarks = ''
        file_size = '123'
        memory_usage = '123kb'
        info = ''
        self.set_info(name, path, create_time, update_time, row, col, remarks, file_size, memory_usage, info)

    def set_info(self, dataset_name: str, path: str, create_time: str,
                 update_time: str, row: str, col: str, remarks: str, file_size: str,
                 memory_usage: str, info=''):

        dataset_info = {"name": dataset_name,
                        "path": path,
                        "create_time": create_time,
                        "update_time": update_time,
                        "row": row,
                        "col": col,
                        "remarks": remarks,
                        "file_size": file_size,
                        "memory_usage": memory_usage,
                        "info": info}
        self.info = dataset_info


class DataHost():
    '''
    '''

    def __init__(self):
        self.vars: Dict[str, Data] = {}
        self.recycle_bin: Dict[str, Data] = {}
        # self.all_data_sets_info: Dict[str, dict] = {}  # 管理数据集的信息

    @property
    def all_data_names(self):
        return [k for k in self.vars.keys()]

    def get_info(self,name:str):
        return self.vars[name].info

    def set_data(self, name: str, value: object) -> None:
        if name in self.vars.keys():
            self.vars[name].set_data(value)
        else:
            self.vars[name] = Data(value)

    def get_data(self, name: str, copy_val: bool = True) -> object:
        if name in self.vars.keys():
            return self.vars[name].get_data(copy_val=copy_val)
        else:
            warnings.warn("Variable \'%s\' isn\'t exist." % name)

    def move_data_stack_pointer(self, name: str, step: int = 1):
        if name not in self.vars.keys():
            return
        var = self.vars[name]
        pos = var.stack_pointer + step
        if 0 <= pos < len(var):
            var.stack_pointer = pos
        elif pos < 0:
            var.stack_pointer = 0
            print('到达最初数据，不可再撤销！')
        elif pos >= len(var):
            var.stack_pointer = len(var) - 1
            print('到达最新数据，不可再重做！')

    def move_data_stack_pointer_to(self, name: str, pos: int = -1):
        if name not in self.vars.keys():
            return
        var = self.vars[name]
        if pos < 0:
            pos = len(var.value_stack) - pos

        if 0 <= pos < len(var):
            var.stack_pointer = pos
        elif pos < 0:
            var.stack_pointer = 0
            print('到达最初数据，不可再撤销！')
        elif pos >= len(var):
            var.stack_pointer = len(var) - 1
            print('到达最新数据，不可再重做！')

    def delete_data(self, name: str) -> None:
        '''删除数据，也就是移动到回收站。'''
        if name in self.vars.keys():
            self.recycle_bin[name] = self.vars[name]
            self.vars.pop(name)
        else:
            warnings.warn("Variable \'%s\' isn\'t exist." % name)

    def recover_data(self, name: str) -> None:
        '''恢复数据'''
        if name in self.recycle_bin.keys():
            self.vars[name] = self.recycle_bin[name]
            self.recycle_bin.pop(name)
        else:
            warnings.warn("Variable \'%s\' isn\'t exist." % name)
